TestController, Configuration of non SCPI devices

FirstImage

The program supports many different devices, not all uses SCPI, to handle them there are a some build in drivers that will translate between a simplified SCPI and the actual instrument protocol. Some of these drives are nearly fully hard coded, i.e. the device file basically list the name of the device, other can be configured with a device file.
For most of these drivers the only practical configuration that can be done without programing is declaring similar devices.
I will not be explaining most tags, see the SCPI configuration for more explanation.

Content
    Single value
    Binary DMM protocol
        matchSpecification
        Example
    Modbus serial & network
        Modbus register types
        Commands to access the registers
        Unsupported commands
        Defining commands
        Other commands
        Modbus error codes
        Definitions that uses this driver
    Non-SCPI ascii devices (Ascii)
        Commands to write and read values
        Defining commands
        Other commands
        Skeleton example
        Definitions that uses this driver
    Non-SCPI ascii devices with binary envelope (AsciiBin)
    Binary with fixed communication blocks (Block)
        Commands to write and read values
        Format specification
        Defining commands
        Checksum and CRC
        Other commands
        Configuration for streaming data
        Configuration for polling data
    Ascii variable length communication blocks, can be multi line ascii (AsciiBlock)
        Configuration for streaming mode
        Configuration for polled mode
        Command mode
        Format specification
        Checksum and CRC
        Other commands
Main page
Functions for use in calculator and definitions


Single value

This driver is for device that returns a single line with a single value on it. It can be something like this: "DC 45.3 mV" or "456.45".
The value can be returned at regular intervals or after a poll.

The first part is similar to SCPI definitions:

Code:
#idString first two parts of *idn? answer
#name The device name
#handle A short handle
#port The port used
#baudrate Baudrate for serial devices
#eol Used to change the standard LF end of line to CR or CRLF or disable with \_.

The id string must be constructed to look similar to real id strings, typical: "brand, brand model,"

To load this driver use:
Code:
#driver SingleValue

Next comes data type definition, either a single line without a selector or multiple lines with a selector matching the mode. Mode will be constructed from letters in the original line, start TestCOntroller in debug mode to see what it is for different modes.

A device with a single mode
Code:
#value Frequency  Hz SI

Device with multiple modes
Code:
#value VoltageDC V d4 DCV
#value CurrentDC A si DCA
#value VoltageAC V d4 ACV
#value CurrentAC A si ACA
#value Resistance ohm si RESISTANCEOHM

Meters will usually use a text for error condition and may also use it for some other stuff.
Code:
#valueText value text
#valueText value "text"

;Examples:
#valueText OL OL
#valueText -OL "-  OL"
#valueText 1 OPEN
It is possible to use OL or -OL as values. To include spaces in the text it must be in quotes.
The text is checked before checking for modes and if a match is found it is removed from the input before assembling the mode string.


The last entry is optional, it is only used if the device must be polled for the string:
Code:
#askValues poll

It is possible to use escapes in the poll, i.e. \r for a return character or 0x17 for character 17 hex.
This poll will be combined with the #EOL value that has a default value of \n (i.e. a linefeed character). Defining "#eol \_" will disable the end of line character.

Example 1
Code:
#idString HKJ,HKJ Test
#name HKJ Test
#handle Test
#port comfixedbaud
#baudrate 1200
#eol \_
#driver SingleValue

#value VoltageAC V d5 ACV
#value VoltageDC V d5 DCV
#value Resistance V d5 RESISTANCEohm

#askValues \r

Example 2
Code:
#idString HKJ,HKJ Test
#name HKJ Test
#handle Test
#port comfixedbaud
#baudrate 1200
#driver SingleValue

#value Frequency Hz SI

For a complete example see the Protek506 definition file.



Binary DMM protocol

This protocol can handle fixed length binary data formats from a DMM, both with digits as Ascii values or as 7 segment values. It is part of the DMM2 and USBHIDDMM driver and is activated with:

Code:
#driver DMM2
#subDriver Definition

or

#driver USBHIDDMM
#subDriver Definition

The first definition is the data message format with the length and start detection bytes:

Code:
#dataFormat length firstByte firstByteMask

#dataFormat 15 0x02
#dataFormat 13 0x30 0xf0
#dataFormat 13 0 0
length specify the length in bytes.
firstByte is the first byte in the message.
firstByteMask is a mask to define what bytes to compare, (use 0xff for all bits and 0 to accept any byte). When missing 0xff is assumed.


For 7-segments displays the segments must be defined:

Code:

#segments stringWithA-F
#segments byteOfs stringWithA-F byteOfs stringWithA-F byteOfs stringWithA-F byteOfs stringWithA-F

#segments "....afe.....bgcd"
The stringWithA-F must be 8, 16, 24 or 32 characters long, depending on number of bytes used for each digit. Any character not in the A-F range is a unused position.
If the segments for the digits are non-sequential the second format must be used, any number of "byteOfs stringWithA-F" pairs can be specified and is numbered in sequence with the first one as digit 1.

If the display has a "1" digit that is outside the normal segment definition, use:
Code:
#addDigit digits matchSpecification
This will add the digits before the display reading. This is first done after decimal point processing.


The actual value is read with:

Code:
#digits byteOfs digits
#digits digit digits

#digits 1 5
byteOfs is how many bytes from the start of the data the digits starts.
digit is only used when the segment decoder contains the byteOfs (See #segments definition)
digits is the number of digits to read (Not the number of bytes). If lsb is first use a negative digit specification.

The sign is nearly always needed to show negative values, in some cases a overload flag must be used to reliable detect overload:
Code:
#sign matchSpecification
#overload matchSpecification

#sign b(7,"xxxxx1xx")
#overload b(7,"xxxxxxx1")

The above number do not contain any decimal point or adjustment for range, this is done with:

Code:
#point digit matchSpecification

#point 3 b(9, "xxxxxxx1")
#point 2 b(7,"xxxxxxx1")
#point 1 b(5,"xxxxxxx1")
When used there will usually be multiple of these specifications, but often one or two less than there are digits.
This specification is usually only used for 7-segment coding, not for ascii coding.

In addition to the decimal point a multiplier must be used to adjust the number:
Code:
#point factor matchSpecification

#mult M b(11, "xxxxxx1x")
#mult k b(11, "xxxxxxx1")
#mult m b(13, "xxxxxxx1")
#mult 1e0 v(0,0x30)
#mult 1e1 v(0,0x31)
#mult 1e2 v(0,0x32)
The factor is either a SI prefix, matching the segment on the display or just a numeric factor.

Next the range or mode must be defined:
Code:
#range mode
#range - matchSpecification
#range mode matchSpecification
#range mode /factor matchSpecification
#range mode *factor matchSpecification

#range Ohm b(12, "xxxxx10x")
#range F b(13, "xxxxx1xx")
#range F /1e12 v(6,0x36)

#range - !b(12, "00001101")
#range - b(14, "xxxxx11x") | !b(14, "1110xxxx")
mode is a string matching the internal mode table, it can be one of V A F Ohm Hz % TempC TempF %mA dB dBm W VA VAR Wh
factor is either multiplied or divided with the display value and is typically used for ascii formats.

A range without a matchSpecification sets a default range or mode for the driver, this is useful when starting on a specification, but is best removed when finished.
The mode = - is a stop specification (No value is decoded) and is used to block invalid messages or states.

All the modes are tested in the specified sequence and the testing will stop at the first match.

In addition to the above there is AC/DC specifications, they are added to the above modes when present:
Code:
#rangeAC matchSpecification
#rangeDC matchSpecification

#rangeDC b(10,"xxxx1xxx")
#rangeAC b(10,"xxxxx1xx")
They only work for modes where a AC/DC/ACDC mode is relevant (V A W Wh).


With the above most multimeters will work, but some chips have a few special issues that cannot be handled with that easily.
Some issues are handled automatic:
For anything else a script can be added to a range/mode:
Code:
#modify1 matchSpecification
#modify2 matchSpecification
#modify range expression

#modify VAC (mult==1)?value/1e5:value
#modify Hz (mult>5)?value/10:value

To handle this it is possible to use expressions to process the value. The modify1/2 is optional flags.
There are some variables:
value: The value with decimal point (from #point) placed.
mult: The multiplier made from #range & #mult specifications.
modify1: Result from #modify1
modify2: Result from #modify2



matchSpecification

This specification will return true or false, depending on if it matches the specified bytes or not. There are a couple of different formats, the "b" is the basic format, the other formats are for convenience.

Code:
b(byteOfs,bitmask)
s(byteOfs,segmentList)
c(byteOfs,character)
v(byteOfs,value)

b(14, "xxxxx01x")
s(9,"adef")
c(9,"C")
v(6,0x3d)
byteOfs is the offset into data
bitmask is 0/1 bits, any other character will assume a do not care position. It must have exactly 8 characters
segmentList is a list of segments to be on in a digit, i.e. letters from A to F
character will match a ascii character, with 7-segment only "0-9, L E F C r" is recognized
value is a integer value either in decimal or hex and must match the full byte.

The result from a matchSpecification can be inverted with a ! in front of it, this will not affect matchSpecification after this one:
Code:
!b(14, "xxxxx01x")

It is possible to chain multiple matchSpecification on a line:
Code:
b(14, "xxxxx01x") & s(9,"adef")
b(14, "xxxxx01x") | s(9,"adef")
& means both must be true
| means at least one of them must be true.



Example

Download some examples in a zip file

These are complete definitions matching the internal hard coded definition.



Modbus serial & network

Modbus is a packet based interface, with a couple of fixed formats based in a hardware model with different types of input/output.
This protocol is build on top of SCPI and requires all the stuff that a normal SCPI definition does, in addition to a couple of #scpiCmd definitions.

Modbus register types
Register can be read/write or read only types, this is (hopefully) listen in the device manual.
The 4 different types of registers do not necessarily share address space, i.e. the same address can be different things in the different register types. It is common to combine holding registers to 32 bit data as long or float values.



Commands to access the registers

These commands can be used directly from the command line, but this is mostly for test. The Coil? & dInput? will return all bits in a single number, the other command will return a list of values.
The address can be in decimal or in hex by prefixing with 0x
Reading commands has a optionally count, when not specified one value is read, when specified it defines how many values to read.
The L, SL and F prefix works with 32 bit values for either unsigned integers, singed integer or floats.
The *factor or /factor is used to scale the values, i.e. use /10 to divide by 10 or *10 to multiply by 10
The &mask can be used to remove undefined bits and can be something like "&0xff" to only return 8 bits from the 16 bit answer
The unitId command only works for modbus TCP and will set the unit identifier.
The holdingBytes? uses return the a string with all data bytes from the answer that can be typecast to bytes  and must be processed with a :readmath:


Unsupported commands

Do not expect a device to support all the different register access commands, not all registers may be implemented and writing may be restricted to 1 or many registers.
Because TestController automatic select between single and multi register write, there will be a problem with devices not supporting single write (A single write can be simulated with a multi write where the count is 1). To force TestController into always using multi write use this define in the definition file:
Code:
#disableWriteSingle 1



Defining commands

The above commands are only supposed to be used for defining other commands with. By defining commands it makes the definition easier to read and it also makes it easier to directly give commands on the command line.

The format is fairly simple:
Code:
#scpiCmd name register access command with parameters

;Examples:
#scpiCmd Current holdingF 0xa01 (value)
#scpiCmd Current? holdingF? 0xa01
Use (value) to insert parameters from the "name" command. It is possible to use value multiple times and it is also possible to use an expression inside the brackets.
If a value needs to be carried between scpiCmd it can be saved with a ":setvar:" tag
Code:
;Save input value
#scpiCmd mode holding 0xa00 (value)
:setvar: currentMode=value

;Save answer
#scpiCmd mode? holding? 0xb04 1 &0xff
:setvar: currentMode=value

;Using the saved value
#scpiCmd on holding 0xa00 (currentMode);holding 0xa00 (getElement("43 42",value))
It is important that this variable is created before it is used. To do this use a command in "#initCmd" that has a :setVar: for the variable.



Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note mode? is defined with "#scpiCmd model? holding? 0xb06" (I could have used the holding? directly).
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...

Not all devices can handle a steady communication, some needs a small delay between each message to work correctly. This is done with this optional setting:
Code:
#cmdDelayTime time in ms

;Example
#cmdDelayTime 50


The standard modbus driver is RTU, but it can be switched to the TCP driver with:
Code:
#subDriver TCP
#subDriver RTU// Is also valid, but not needed
#subDriver Kunkin// Kunkin modbus format including swapped crc bytes
#subDriver Kunkinx// Kunkin modbus format, used in newer versions of the Kunkin software
#subDriver Ascii
When using modbus TCP the #port will usually need to be defined as "#port 502"



Modbus error codes
TestController will return error codes as negative value, i.e. -1 is error 1.

Definitions that uses this driver

The power supply definitions RidenRD6006 uses this driver. It has a fairly advanced configuration menu.

Maynuo M97xx definition is a electronic load.



Non-SCPI ascii devices (Ascii)

This interface will work with devices that requires strings of ascii commands, but are not SCPI compliant. It works in a similar way to the Modbus definition.
This protocol is build on top of SCPI and requires all the stuff that a normal SCPI definition does, in addition to a couple of #scpiCmd definitions.
Code:
#driver Ascii



Commands to write and read values

These commands can be used directly from the command line, but this is mostly for test. In a #scpiCmd definition the ; is transmitted directly.
The Bin commands do not use specified EOL format, it must be included in the cmd (See escape codes below).
It is very important to use command that waits for an answer, if the cmd will return an answer.
Escape codes for bin commands: \b \t \n \r \\ \" \' \u0000 \x00, \u is followed by a four digit unicode hex value, \x is followed by a two digit hex code.



Defining commands

The above commands are only supposed to be used for defining other commands with. By defining commands it makes the definition easier to read and it also makes it easier to directly give commands on the command line.
The scpiCmd has shares a common context, this means it is possible to use :setvar: and then reference to the variable in another #scpiCmd.

The format is fairly simple:
Code:
#scpiCmd name tx cmd
#scpiCmd name txrx cmd
#scpiCmd name? txrx? cmd
#scpiCmd name? txrx? cmd
#scpiCmd name? txrx2? cmd
#scpiCmd name? txrxn? lines cmd
#scpiCmd name? txrxnBin? bytes cmd
#scpiCmd name? txrx1Bin? cmd
#scpiCmd name txrxnBin bytes cmd
#scpiCmd name txrx1Bin cmd

#scpiCmd name tx cmd (value)
#scpiCmd name txrx cmd (value)
#scpiCmd name? txrx? cmd (value)
Use (value) to insert parameters from the "name" command. It is possible to use value multiple times and it is also possible to use an expression inside the brackets.

On the :readmath: and :setVar: tags a valueInput can be used to access the this value, the "value" parameter will show the return value.

A number or n in the command lines means multiple lines, except with bin where it means bytes (Up to 8, answer is return as a number).
If a value needs to be carried between scpiCmd it can be saved with a ":setvar:" tag
Code:
;Save input value
#scpiCmd name tx (value)
:setvar: currentMode=value

;Save answer
#scpiCmd name? txrx? cmd
:setvar: currentMode=value

;Using the saved value
#scpiCmd name tx (currentMode)
It is important that this variable is created before it is used. To do this use a command in "#initCmd" that has a :setVar: for the variable.



Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note model? must defined with "#scpiCmd model? 
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...

Not all devices can handle a steady communication, some needs a small delay between each message to work correctly. This is done with this optional setting:
Code:
#cmdDelayTime time in ms

;Example
#cmdDelayTime 50



Skeleton example

Use the below skeleton when starting a new definition.
Code:
#idString brand,brand model
#name brand model
#handle mostlyModel

#driver Ascii

; port can be com, comfixedbaud, comnobaud or a port number for network devices.
#port 5025

; Baudrate definition is needed for comfixedbaud types.
;#baudrate 9600

; The author statement is used for the listing in the About window.
;#author you name or handle

; There must be a line for each of the original device commands that will be used, converting it to a similar SCPI command
;#scpiCmd init tx command to init
;#scpiCmd values? txrx? command to read current value or values. It is possible to define value1?, value2?, etc. and then use them all with a ; between in the #askValues statement.

; A list of possible column name with unit and formatter (SI, Time, Int, D0..D6)
#value Voltage V SI
 
; Use these commands to get a full id line and prevent connection to other devices
;#verifyDevice value commandToGetvalue
;#scpiCmd getDeviceSW? ...
;#scpiCmd getDeviceSN? ...

; This is a single line command
#askValues values?

;Accept this delay when reading values (seconds)
#readingDelay 5

; Prepare the meter to response to #askValues
;#prepareSample

; Initial commands to meter when establishing connection
;#initCmd

; Final command to meter before breaking connection
;#finalCmd 

; Used when output off button is pressed
;#outputOff 


Definitions that uses this driver

FeelElecFY6x00-xxM defines many ARB models using this driver.
HP3478A is a device from before SCPI.



Non-SCPI ascii devices with binary envelope (AsciiBin)

This driver is very similar to the ascii driver, but will handle a binary envelope around the messages. It supports the same definitions as the ascii driver, with the addition that a packet format must be specified.
Code:
#driver AsciiBin
#packetFormat name

The supported packet format (envelope) names are:
Note: txrxn? and txrx2? is not supported.



Binary with fixed communication blocks (Block)

This driver can handle binary protocols with fixed length messages, it is possible to extract one or more values from each message.
Code:
#driver Block


Commands to write and read values

These commands can be used directly from the command line, but this is mostly for test. byteSequence is a list of numbers, both decimal and hex is accepted.
/ when present will disable the default unsigned integer conversion and expect format specifiers instead.
format makes it possible to interpret the answer as any data type and can handle more than 8 bytes.
It is very important to use command that waits for an answer, if the cmd will return an answer.
These commands are not used with streaming data.



Format specification

One or more formats can be specified and each will return a number/string. The general format is:

byteIndex dataType bytes {multiplier} {offset}
All elements must be combined without any space between. There is no restriction on rxnz! modifiers, but there is only a few combinations that are useful.

Some examples: The function makeDouble() can be used in a #askValuesMathFormat or :readmath: to assemble double numbers from a couple of integer values.



Defining commands

The above commands are only supposed to be used for defining other commands with. By defining commands it makes the definition easier to read and it also makes it easier to directly give commands on the command line.

The format is fairly simple:
Code:
#scpiCmd name tx byteSequence
#scpiCmd name txrx1 byteSequence
#scpiCmd name txrx2 byteSequence
#scpiCmd name txrxn count byteSequence
#scpiCmd name? txrx1? byteSequence {/ format}
#scpiCmd name? txrx2? byteSequence {/ format}
#scpiCmd name? txrxn? count byteSequence {/ format}
Use (value) to insert parameters from the "name" command, each () must return a byte sized value. It is possible to use value multiple times and it is also possible to use an expression inside the brackets.
If a value needs to be carried between scpiCmd it can be saved with a ":setvar:" tag


Checksum and CRC

The driver supports adding a checksum or CRC to the transmitted messages, this is done with:

Code:
#checksum type addFormat firstByte initValue poly xor

#checksum crc16 binhl 0 0 0x8005 0
#checksum crc16r binhl 0 0 !0x8005 0

type can be one of: crc8, crc8r, crc16, crc16r, crc32, crc32r, sum8, sum16, msum8, msum16, xor8
addFormat can be one of: binhl, binlh, hexhl, hexlh (hl/lh is ignored for 8 bit values)
firstByte is first byte to include in calculation, this is often 0
initValue is the initial value of the check, this is often 0 of 0xffff
poly is the actual CRC polynomial, prefix with ! to reflect it.
xor A non zero value will invert bits in the specified positions in the final result.

The formats with r (i.e. crc16r) is reflected version and must be used with the reflected version of the polynomial

For poly values see https://crccalc.com/ To get values where refIn & refOut is true use the r version and place a ! before the polynomial



Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note model? must defined with "#scpiCmd model? 
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...

Not all devices can handle a steady communication, some needs a small delay between each message to work correctly. This is done with this optional setting:
Code:
#cmdDelayTime time in ms

;Example
#cmdDelayTime 50

To always add some bytes to the end of the message, this is added after any checksum.
Code:
#eol \r


Configuration for streaming data

For devices that sends a data message at regular intervals use these tags to configure the Block driver for it.

Code:
#rxStart initial bytes in messages
#rxEnd Final bytes in message, this can be used instead of #rxStart
#rxLength number of bytes in message including initial bytes
#rxFormat format, see "Format specification"
#askValues values?// Must use "values?", it is possible to add #askValuesMathFormat to do further processing of the values
#pollPause delay// Delay in milliseconds between polls, default is 50ms

#rxStart \x0241// This is the initial bytes: 0x02 0x34 0x31
#rxLength 64
#rxFormat 8i4 12i4



Configuration for polling data

To poll a device at regular intervals for data, use these tags to configure the Block driver for it.

Code:
#rxStart initial bytes in messages
#rxEnd Final bytes in message, this can be used instead of #rxStart
#rxLength number of bytes in message including initial bytes
#rxFormat format, see "Format specification"
#poll byteSequence, will send this message at regular intervals. This must be all bytes for the poll, no checksum or eol is added.
#askValues values?// Must use "values?", it is possible to add #askValuesMathFormat to do further processing of the values


#rxStart \x0241// This is the initial bytes: 0x02 0x34 0x31
#rxLength 64
#rxFormat 8i4 12i4
#poll "send"



Ascii variable length communication blocks, can be multi line ascii (AsciiBlock)

This driver can handle Ascii protocols with variable length messages, received data is filtered with a regular expression. The driver has 3 operating modes, they are streaming, polled and command.
Code:
#driver AsciiBlock



Configuration for streaming mode

For devices that sends a data message at regular intervals use these tags to configure the AsciiBlock driver for it. Communication is done in the background.
This driver uses the binary communication drivers, this avoids any inherited dependence on CR and LF characters.

Code:
#rxStart initial bytes in messages, this can be empty, but this may make the communication unstable.
#rxEnd final bytes in message, can be \r\n
#rxCount number of times to receive #rxEnd, i.e. number of lines for a multiline ascii, when missing 1 is assumed.
#rxFormat format, see "Format specification"
#askValues values?// Must use "values?", it is possible to add #askValuesReadFormat and #askValuesMathFormat to do further processing of the values

#rxStart Da:
#rxEnd \r\n\r\n
#rxFormat .*?([0-9.E+-]+).*?([0-9.E+-]+).*?([0-9.E+-]+)
#askValues Values?

#askValuesReadFormat can be useful for filtering the result from #rxFormat
The #rxEnd activate background mode as either streaming or polled mode.


Configuration for polled mode

Polled mode works nearly the same as streaming mode, except a poll must be send to get the data. Communication is done in the background.

Code:
#rxStart initial bytes in messages.
#rxEnd final bytes in message, can be \r\n
#rxCount number of times to receive #rxEnd, i.e. number of lines for a multiline ascii, when missing 1 is assumed.
#poll String to request data, the specification of poll must include any required CR, LF or other characters
#rxFormat format, see "Format specification"
#askValues values?// Must use "values?", it is possible to add #askValuesReadFormat and #askValuesMathFormat to do further processing of the values


#rxStart Da:
#rxEnd \r\n\r\n
#poll data?
#rxFormat .*?([0-9.E+-]+).*?([0-9.E+-]+).*?([0-9.E+-]+)
#askValues Values?

#askValuesReadFormat can be useful for filtering the result from #rxFormat
The #rxEnd activate background mode as either streaming or polled mode.


Command mode

In this mode commands must be send and answers to these received. These commands can be used directly from the command line, but this is mostly for test.
The command will work in any mode, but are best used only in command mode, in streaming mode they may fail, due to the background communication.
These commands are generally used together with #scpiCmd cmd is a ascii string
/ is followed by a regular expression, see format below.
It is very important to use command that waits for an answer, if the cmd will return an answer.

Some other tags that can be useful:

Format specification

The format is a regular expression where all groups are returns as answer. Due to the complexity of regEx there is a shortcut method to generate the necessary expression.

Using regular expressions

To way to extract numeric results is to use the following regEx:
Code:
.*?([0-9.E+-]+) 
for each number in the answer, i.e. a answer with 3 numbers will use:
Code:
.*?([0-9.E+-]+).*?([0-9.E+-]+).*?([0-9.E+-]+)
to decode all 3 numbers (This is a simplified regEx to match a number and will match some non-numeric items)

A short explanation:
More complex regex expression can be used for a more precise filter. See Java documentation for a explanation of all the elements that can be used in a regular expression.

The format cannot be specified on the command line, because a ( will switch to calculator mode, there is a way around that that can be used when testing.
Define the command including format as a variable, then use the calculator mode to return the command.
Code:
=var cmd="txrxn? 2 cmd / .*?([0-9.E+-]+).*?([0-9.E+-]+).*?([0-9.E+-]+)
(cmd)

Using the simplified way

Instead of the above it is possible to build a similar regEx with a few letters, this method works when the format do not contain any parentheses.
Use one of the letters: This matches the letters used in #askValuesReadFormat

This means a format with "fxf" will return the first and third number and skip the second.



Checksum and CRC

The driver supports adding a checksum or CRC to the transmitted messages, this is done with:

Code:
#checksum type addFormat firstByte initValue poly xor

#checksum crc16 binhl 0 0 0x8005 0
#checksum crc16r binhl 0 0 !0x8005 0

type can be one of: crc8, crc8r, crc16, crc16r, crc32, crc32r, sum8, sum16, msum8, msum16, xor8
addFormat can be one of: binhl, binlh, hexhl, hexlh (hl/lh is ignored for 8 bit values)
firstByte is first byte to include in calculation, this is often 0
initValue is the initial value of the check, this is often 0 of 0xffff
poly is the actual CRC polynomial, prefix with ! to reflect it.
xor A non zero value will invert bits in the specified positions in the final result.

The formats with r (i.e. crc16r) is reflected version and must be used with the reflected version of the polynomial

For poly values see https://crccalc.com/ To get values where refIn & refOut is true use the r version and place a ! before the polynomial



Other commands

A few more commands are supported.

To verify it is the correct device that is connected use this command. Often it is possible to read a model number from the device and compare that to the value.
Code:
#verifyDevice value commandToGetvalue

;Example, note model? must defined with "#scpiCmd model? 
#verifyDevice 2 model?

The software always ask for serial number and software versions when connecting to a device, by defining these two command they will be read:
Code:
#scpiCmd getDeviceSW? ...
#scpiCmd getDeviceSN? ...